package org.modelcc.io.java.visitor;

import java.lang.reflect.Method;
import java.util.logging.Level;

import org.modelcc.Setup;
import org.modelcc.io.java.JavaModelReader;
import org.modelcc.io.java.JavaLanguageVisitor;
import org.modelcc.io.java.JavaLanguageClass;

/**
 * Java model reader: Class visitor for @Setup
 * 
 * @author Fernando Berzal (berzal@acm.org)
 */
public class SetupVisitor extends JavaLanguageVisitor 
{	
	private Method setupMethod = null;
	private boolean error = false;
	
	public SetupVisitor(JavaModelReader reader)
	{
		super(reader);
	}
	
	@Override
	public void startVisit(Class type, JavaLanguageClass element) 
	{
		setupMethod = null;
		error = false;		
	}

	@Override
	public void visit(Class type, Method method, JavaLanguageClass element) 
	{
		if (method.isAnnotationPresent(Setup.class)) {
			if (method.getReturnType()!=void.class) {
				log(Level.SEVERE, "In method \"{0}\" of class \"{1}\": The @Setup annotation can only be assigned to a method that returns void.", new Object[]{method.getName(), type.getCanonicalName()});
				error = true;
			}
			if (method.getParameterTypes().length!=0) {
				log(Level.SEVERE, "In method \"{0}\" of class \"{1}\": The @Setup annotation can only be assigned to a method with no parameters.", new Object[]{method.getName(), type.getCanonicalName()});
				error = true;
			}
			if (setupMethod == null) {
				setupMethod = method;
			} else {
				if (!error) {
					log(Level.SEVERE, "In method \"{0}\" of class \"{1}\": The @Setup annotation can only be assigned to a single method.", new Object[]{setupMethod.getName(), type.getCanonicalName()});
					error = true;
				}
				log(Level.SEVERE, "In method \"{0}\" of class \"{1}\": The @Setup annotation can only be assigned to a single method.", new Object[]{method.getName(), type.getCanonicalName()});
			}
		}
	}

	@Override
	public void endVisit(Class type, JavaLanguageClass element) 
	{
		if (error)
			setupMethod = null;

		element.setSetupMethod(setupMethod);
	}

}
